package cn.wolfcode.shop.service.impl;

import cn.wolfcode.shop.common.BusinessException;
import cn.wolfcode.shop.common.Result;
import cn.wolfcode.shop.domain.Good;
import cn.wolfcode.shop.domain.SeckillGood;
import cn.wolfcode.shop.feign.GoodFeignApi;
import cn.wolfcode.shop.mapper.SeckillGoodMapper;
import cn.wolfcode.shop.mq.MQConstants;
import cn.wolfcode.shop.redis.RedisTemplate;
import cn.wolfcode.shop.redis.SeckillServerKeyPrefix;
import cn.wolfcode.shop.service.ISeckillGoodService;
import cn.wolfcode.shop.vo.SeckillGoodVo;
import cn.wolfcode.shop.web.result.SeckillServerCodeMsg;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class SeckillGoodServieImpl implements ISeckillGoodService{

    @Autowired
    private SeckillGoodMapper seckillGoodMapper;

    @Autowired
    private GoodFeignApi goodFeignApi;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public List<SeckillGoodVo> query() {
        //1.查询所有的SeckillGood对象
        List<SeckillGood> seckillGoodList = seckillGoodMapper.list();
        List<SeckillGoodVo> seckillGoodVoList = getSeckillGoodVos(seckillGoodList);
        return seckillGoodVoList;
    }

    public SeckillGoodVo find(Long seckillGoodId) {
        return redisTemplate.hget(SeckillServerKeyPrefix.SECKILL_GOODS_HASH,"",seckillGoodId+"",SeckillGoodVo.class);
        /*SeckillGood seckillGood = seckillGoodMapper.selectByPrimaryKey(seckillGoodId);
        if (seckillGood == null){
            return null;
        }
        List<SeckillGood> list = new ArrayList<>();
        list.add(seckillGood);
        List<SeckillGoodVo> seckillGoodVos = getSeckillGoodVos(list);
        return seckillGoodVos.get(0);*/
    }

    public int reduceStock(Long seckillGoodId) {
        return seckillGoodMapper.reduceStock(seckillGoodId);
    }

    public List<SeckillGoodVo> queryByCache() {
        Map<String, SeckillGoodVo> map = redisTemplate.hgetAll(SeckillServerKeyPrefix.SECKILL_GOODS_HASH, "", SeckillGoodVo.class);
        return new ArrayList<>(map.values());
        /*List<SeckillGood> list = seckillGoodMapper.list();
        List<SeckillGoodVo> seckillGoodVos = getSeckillGoodVos(list);
        return seckillGoodVos;*/
    }

    public void syncStock(Long seckilGoodId) {
        int stock = seckillGoodMapper.getStock(seckilGoodId);
        if (stock > 0){
            // 把真实库存同步到redis中的预库存
            redisTemplate.set(SeckillServerKeyPrefix.SECKILL_GOOD_STOCK,seckilGoodId+"",stock);
            // 取消本地标识
            rabbitTemplate.convertAndSend(MQConstants.SECKILL_OVER_SIGN_PUBSUB_EX,"",seckilGoodId);
        }
    }

    public void incrStock(Long seckillGoodId) {
        seckillGoodMapper.incrStock(seckillGoodId);
    }

    private List<SeckillGoodVo> getSeckillGoodVos(List<SeckillGood> seckillGoodList) {
        //2.根据SeckillGood集合,获取到对应的goodId集合[1,2]
        Map<Long,SeckillGood> map = new HashMap<>();
        for(SeckillGood sg:seckillGoodList){
            map.put(sg.getGoodId(),sg);
        }
        List<Long> ids = new ArrayList<>(map.keySet());
        // 3.远程调用,把需要查询的商品id[1,2]作为参数传递商品服务,查询对应的Good对象集合
        Result<List<Good>> result = goodFeignApi.queryByIds(ids);

        if(result==null||result.hasError()){
            throw new BusinessException(SeckillServerCodeMsg.PRODUCT_ERROR);
        }
        List<Good> goodList = result.getData();//远程调用
        //4.循环,把Good和SeckillGood对象封装SeckillGoodVo对象,返回.
        List<SeckillGoodVo> seckillGoodVoList = new ArrayList<>();
        SeckillGood sg = null;
        SeckillGoodVo vo = null;
        for(Good good:goodList){
            sg = map.get(good.getId());
            vo = new SeckillGoodVo();
            vo.setId(sg.getId());
            vo.setGoodDetail(good.getGoodDetail());
            vo.setGoodId(good.getId());
            vo.setGoodImg(good.getGoodImg());
            vo.setGoodName(good.getGoodName());
            vo.setGoodPrice(good.getGoodPrice());
            vo.setGoodTitle(good.getGoodTitle());
            vo.setEndDate(sg.getEndDate());
            vo.setSeckillPrice(sg.getSeckillPrice());
            vo.setStartDate(sg.getStartDate());
            vo.setStockCount(sg.getStockCount());
            seckillGoodVoList.add(vo);
        }
        return seckillGoodVoList;
    }
}
